package com.ibeeking.found.report.rest.controller.v1;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ibeeking.found.common.annotation.LoginUser;
import com.ibeeking.found.common.entity.CurrentUser;
import com.ibeeking.found.report.rest.service.IBaseService;
import com.ibeeking.found.report.rest.service.util.ReportBeanUtils;
import com.ibeeking.found.report.service.common.dos.ReportBaseDO;
import com.ibeeking.found.report.service.common.po.BaseResponse;
import com.ibeeking.found.report.service.common.po.ResponseBean;
import com.ibeeking.found.report.service.common.query.BasePageQuery;
import com.ibeeking.found.report.service.common.vo.ReportBaseVO;
import com.ibeeking.nematos.constants.enums.OperateLogTypeEnum;
import com.ibeeking.nematos.log.annotation.Log;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.json.JsonUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.io.Serializable;
import java.util.HashMap;
import java.util.List;

/**
 * 项目级的Controller公共处理基类
 *
 * @author WongBin
 * @date 2021/3/26
 */
public abstract class DmpBaseController<P extends BasePageQuery, T extends ReportBaseDO, D extends ReportBaseVO>  extends BaseResponse {

    /**
     * 获取实际服务类
     *
     * @return
     */
    public abstract IBaseService<P, T> getService();

    /**
     * 获取当前Controller数据库实体Entity
     *
     * @return
     */
    public abstract T getEntity();

    /**
     * 获取当前Controller数据传输DTO
     *
     * @return
     */
    public abstract D getDTO();

    /**
     * 分页模板
     *
     * @param param
     * @return
     */
    @Log(logType = OperateLogTypeEnum.QUERY, describe = "分页查询")
    @GetMapping("/pageList")
    public ResponseBean pageList(P param) {
        IPage<T> iPage = getService().page(param);
        List<T> records = iPage.getRecords();

        //entity转换成DTO
//        List<D> list = (List<D>) ReportBeanUtils.copyList(records, getDTO().getClass());
        List<D> list = (List<D>) JsonUtils.jsonToList(records, getDTO().getClass());
                //处理dto返回结果
        pageResultHandler(list);
        Page<D> pageDto = new Page<>();
        pageDto.setCurrent(iPage.getCurrent())
                .setRecords(list)
                .setPages(iPage.getPages())
                .setTotal(iPage.getTotal())
                .setSize(iPage.getSize());
        return responseSuccessWithData(pageDto);
    }

    /**
     * 对分页dto返回处理
     * @param list
     * @return
     */
    public List<D> pageResultHandler(List<D> list) {
        return list;
    }

    /**
     * 对详情返回DTO进行处理
     * @param detail
     * @return
     */
    public D detailResultHandler(D detail) {
        return detail;
    }


    /**
     * 根据ID查询相关记录
     *
     * @param id
     * @return
     */
    @Log(logType = OperateLogTypeEnum.QUERY, describe = "根据ID查询相关记录")
    @GetMapping("/{id}")
    public ResponseBean detail(@PathVariable("id") Long id) {
        ///logger.info("{}根据ID查询服务开始，id为：{}", this.getClass().getSimpleName(), id);
        T result = getService().selectOne(id);
        D dto = getDTO();
        ReportBeanUtils.copyAndFormatter(result, dto, new HashMap<>());
        //对返回值建处理
        detailResultHandler(dto);
        ResponseBean responseBean = responseSuccessWithData(resultDtoHandle(dto));
        LogUtils.info("根据ID查询结束，req：{},res:{}", id,responseBean);
        return responseBean;
    }

    /**
     * 对明细结果进行处理,子类可以覆盖
     * @param d
     * @return
     */
    protected D resultDtoHandle(D d) {
        return d;
    }

    /**
     * 插入
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @Log(logType = OperateLogTypeEnum.SAVE, describe = "插入记录")
    @PostMapping
    public ResponseBean insert(@LoginUser CurrentUser loginUser, @Validated @RequestBody D dto) {
        ///logger.info("{}新增服务开始，参数：{}", this.getClass().getSimpleName(), ReportUtils.toJSONString(dto));
        T entity = getEntity();
        //dto转为数据库实体
        BeanUtil.copyProperties(dto, entity);
        //插入
        getService().insert(entity);

        ResponseBean ret = responseSuccessWithData(entity.copyTo(dto.getClass()));
        LogUtils.info("新增服务结束，req：{},res:{}", dto,ret);
        return ret;
    }


    /**
     * 根据ID修改对饮记录
     *
     * @param dto
     * @return
     * @throws Exception
     */
    @Log(logType = OperateLogTypeEnum.MODIFY, describe = "修改记录")
    @PutMapping
    public ResponseBean update(@LoginUser CurrentUser loginUser, @Validated @RequestBody D dto) {
        String username = loginUser.getName();
        T entity = getEntity();
        //dto转换entity
        BeanUtil.copyProperties(dto, entity);
        getService().update(entity);
        LogUtils.info("更新服务结束，user:{},req:{},res:{}",username,dto,entity);
        ResponseBean ret = responseSuccessWithData(entity.copyTo(dto.getClass()));
        return ret;
    }


    /**
     * 根据ID删除指定记录,这里被删除的记录会进入删除记录表
     *
     * @param id
     * @return
     */
    @Log(logType = OperateLogTypeEnum.DEL, describe = "根据ID删除记录")
    @DeleteMapping("/{id}")
    public ResponseBean deleteById(@PathVariable("id") Long id) {
        getService().deleteById(id);
        LogUtils.info("删除服务结束:{}", id);
        return responseSuccess();
    }
    /**
     * 更新记录状态
     *
     * @param id
     * @return
     */
    @Log(logType = OperateLogTypeEnum.DEL, describe = "根据ID更新记录状态")
    @DeleteMapping("/changeStatus/{id}/{status")
    public ResponseBean changePublishStatus(@PathVariable("id") Long id, @PathVariable("status") Integer status) {
        getService().changePublishStatus(id, status);
        LogUtils.info("更新记录状态服务结束:{}", id);
        return responseSuccess();
    }

    /**
     * 删除批量ID对应的记录
     *
     * @param ids
     * @return
     */
    @Log(logType = OperateLogTypeEnum.DEL, describe = "根据ID批量删除记录")
    @PostMapping("/delete/batch")
    public ResponseBean deleteBatchIds(@RequestBody List<Serializable> ids) {
        boolean deleteCount = getService().deleteByIds(ids);
        ResponseBean responseBean = responseSuccessWithData(deleteCount);
        LogUtils.info("批量删除服务结束，req:{},ret：{}", ids, responseBean);
        return responseBean;
    }
}
